#include<iostream>
#include<cassert>
#include<string>
#include<vector>
#include<time.h>
#include<unistd.h>
#include<stdio.h>
#include<cstdlib>
#include<wait.h>
#include<sys/types.h>
#define PROCESS_NUM 4
#define RUN_TIME 5
#define MakeSeed()  srand((unsigned long)time(NULL)^0x787800^getpid()^rand()%1234);
using namespace std;
class Subs
{
public:
    Subs(int fd,pid_t pid)
    :_fd(fd),
     _pid(pid)
    {
        char nameBuffer[1024];
        snprintf(nameBuffer,sizeof(nameBuffer),"我是子进程，pid : %d",_pid);
        _name = nameBuffer;
    }
    static int num;
    string _name;
    int _fd;
    pid_t _pid;

};
typedef void(*func_t)();
int recvCommand(int fd)
{
    int tmp;
    ssize_t s = read(fd,&tmp,sizeof(tmp));
    if(s <= 0)
    return -1;
    return tmp;
}
void ProcessCreate(vector<Subs>* subs,vector<func_t> FuncMap)
{
    for(int i = 0;i<PROCESS_NUM;i++)
    {
        int fds[2];
        int n = pipe(fds);
        assert(n == 0);
        //创建子进程
        pid_t id = fork();
        if(id == 0)
        {
            //关闭子进程的写权限
            close(fds[1]);
            while(1)
            {
                //获取命令
                int CommandCode = recvCommand(fds[0]);
                if(CommandCode >= 0 && CommandCode < FuncMap.size())
                FuncMap[CommandCode]();
                else if(CommandCode == -1)
                break;
            }
            exit(0);
        }
        Subs process(fds[1],id);
        subs->push_back(process);
    }
}
void IOTask()
{
    cout<<getpid()<<": IO任务，执行"<<endl;
    sleep(1);
}
void FulshTask()
{
    cout<<getpid()<<": 刷新任务，执行"<<endl;
    sleep(1);

}
void sleepTask()
{
    cout<<getpid()<<": 睡眠任务，执行"<<endl;
    sleep(1);

}
void loadTask(vector<func_t>* FuncMap)
{
    FuncMap->push_back(sleepTask);
    FuncMap->push_back(FulshTask);
    FuncMap->push_back(IOTask);
}
void SendTask(Subs& process , int TaskNum)
{
    int n = write(process._fd,&TaskNum,sizeof(TaskNum));
    assert(n==sizeof(int));
    (void )n;
}
void WaitProcess(vector<Subs> subs)
{
    int process_num = subs.size();
    for(int i = 0;i<process_num;i++)
    {
        waitpid(subs[i]._pid,NULL,0);
        cout<<"wait process success ... pid : "<<subs[i]._pid<<endl;
    }
}
int main()
{
    MakeSeed();
    vector<Subs> subs;
    vector<func_t> FuncMap;
    //为什么这里要用指针？
    //如果不用指针系统会深拷贝，导致只改了函数作用域的vector
    loadTask(&FuncMap);
    //1.先创建进程
    ProcessCreate(&subs,FuncMap);
    //2.父进程进行子进程的控制
    int SubsNum = subs.size();
    int TaskNum = FuncMap.size();
    int j = RUN_TIME;
    while(j--)
    {
        int SubIndex = rand()%SubsNum;
        int TaskIndex = rand()%TaskNum;
        SendTask(subs[SubIndex],TaskIndex);
    }
    for(int i = 0;i<PROCESS_NUM;i++)close(subs[i]._fd);
    WaitProcess(subs);
}